WebSocket 连接状态常量
WebSocket 连接有四种状态,通过 readyState 属性读取:
| 常量 | 值 | 含义 |
|---|---|---|
CONNECTING | 0 | 连接正在建立中 |
OPEN | 1 | 连接已建立,可以通信 |
CLOSING | 2 | 连接正在关闭 |
CLOSED | 3 | 连接已关闭或无法打开 |
在实际开发中,通常不需要手动检查 readyState 来做状态判断,因为 WebSocket 提供了更优雅的事件回调机制。
客户端(浏览器侧)API 详解
浏览器原生 WebSocket 对象提供了四个事件回调和两个方法:
事件回调
const ws = new WebSocket('ws://localhost:3000')
// 连接成功
ws.onopen = function () {
console.log('连接已建立')
}
// 接收服务端消息
ws.onmessage = function (event) {
// event.data 包含服务端发送的数据
// 文本消息为 string 类型,二进制消息为 Blob/ArrayBuffer
console.log('收到消息:', event.data)
}
// 连接错误
ws.onerror = function (error) {
console.error('连接异常:', error)
}
// 连接关闭
ws.onclose = function (event) {
// event.code: 关闭状态码
// event.reason: 关闭原因
console.log('连接已关闭:', event.code, event.reason)
}
javascript
方法
// 发送消息(字符串或二进制数据)
ws.send('hello')
ws.send(JSON.stringify({ event: 'message', data: 'hello' }))
// 主动关闭连接
ws.close(1000, 'normal closure')
javascript
服务端(ws 库)API 详解
ws 库在 Node.js 端使用 EventEmitter 风格的 API,与浏览器侧的写法有显著区别:
const WebSocket = require('ws')
const wss = new WebSocket.Server({ port: 3000 })
wss.on('connection', (ws) => {
// ws 是当前连接的客户端实例
// 接收消息
ws.on('message', (message) => {
console.log('收到:', message.toString())
})
// 发送消息
ws.send('message from server')
// 连接关闭
ws.on('close', (code, reason) => {
console.log('客户端断开连接:', code)
})
// 连接错误
ws.on('error', (error) => {
console.error('连接错误:', error)
})
})
javascript
客户端与服务端 API 对照
| 功能 | 浏览器侧 | Node.js ws 库 |
|---|---|---|
| 连接成功 | ws.onopen = fn | ws.on('open', fn) |
| 接收消息 | ws.onmessage = fn | ws.on('message', fn) |
| 连接错误 | ws.onerror = fn | ws.on('error', fn) |
| 连接关闭 | ws.onclose = fn | ws.on('close', fn) |
| 发送消息 | ws.send(data) | ws.send(data) |
| 关闭连接 | ws.close() | ws.close() |
这个差异必须牢记。浏览器端的 WebSocket 对象是浏览器内置的,使用的是属性赋值语法;Node.js 端的 ws 库基于 EventEmitter,使用的是 on(event, callback) 语法。
双向通信实战
下面的示例演示了服务端和客户端之间的完整双向通信:
服务端 (server/index.js):
const WebSocket = require('ws')
const wss = new WebSocket.Server({ port: 3000 })
wss.on('connection', (ws) => {
console.log('client connected')
// 接收客户端消息
ws.on('message', (message) => {
const data = JSON.parse(message)
console.log('received event:', data.event, 'data:', data.data)
})
// 主动发送消息给客户端
ws.send(JSON.stringify({
event: 'message',
data: 'message from server'
}))
})
javascript
浏览器客户端:
const ws = new WebSocket('ws://127.0.0.1:3000')
ws.onopen = function () {
// 连接成功后立即发送消息
ws.send(JSON.stringify({
event: 'message',
data: 'hello from client'
}))
}
ws.onmessage = function (event) {
const data = JSON.parse(event.data)
console.log('收到服务端消息:', data)
}
javascript
Node.js 客户端:
const WebSocket = require('ws')
const ws = new WebSocket('ws://127.0.0.1:3000')
ws.on('open', () => {
ws.send('client say hello to server')
})
ws.on('message', (message) => {
console.log('message from server:', message.toString())
})
javascript
在 Network 面板中调试 WebSocket
Chrome DevTools 的 Network 面板是调试 WebSocket 的重要工具。连接建立后,请求列表中会出现 WS 类型的条目,点击后在 Messages 标签页可以看到所有发送和接收的消息,包括时间戳和消息内容。
握手请求的特征非常明显:请求头中包含 Upgrade: websocket 和 Connection: Upgrade,响应状态码为 101 Switching Protocols。如果看到这些信息,说明 WebSocket 握手成功。
↑